﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IceCS.DelegateInvoke
{
    class Program
    {
        public delegate int CalcNum(int a, int b);

        static CalcNum calcAdd = new CalcNum((int a, int b) =>
        {
            return a * b;
        });

        static CalcNum calcMinus = (int a, int b) =>
        {
            return a - b;
        };

        static CalcNum calcPlus = new CalcNum((int a, int b) =>
        {
            Task.Delay(2000).Wait();
            return a * b;
        });
        static bool isExit = false;
        static void Main(string[] args)
        {
            //Console.CancelKeyPress += Console_CancelKeyPress;
            //Console.WriteLine("CallCalcNumDirect(calcPlus, 2, 3):");
            //Console.WriteLine(CallCalcNumDirect(calcPlus, 2, 3));

            //Console.WriteLine("CallCalcNumInvoke(calcPlus, 2, 3):");
            //Console.WriteLine(CallCalcNumInvoke(calcPlus, 2, 3));

            //Console.WriteLine("CallCalcNumDynamicInvoke(calcPlus, 2, 3):");
            //Console.WriteLine(CallCalcNumDynamicInvoke(calcPlus, 2, 3));

            Console.WriteLine("CallCalcNumAsyncCallback(calcPlus, 2, 3, Console.WriteLine):");
            CallCalcNumAsyncCallback(calcPlus, 2, 3, Console.WriteLine);

            Console.WriteLine("CallCalcNumAsyncWhileLoop(calcPlus, 2, 3, Console.WriteLine):");
            CallCalcNumAsyncWhileLoop(calcPlus, 2, 3, Console.WriteLine);

            while (!isExit)
            {
                Task.Delay(1000).Wait();
                Console.WriteLine("主线程存活中...");
            }
        }

        private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            Console.WriteLine("主线程退出成功");
            isExit = true;
        }

        /// <summary>
        /// 直接调用存储过程
        /// </summary>
        /// <param name="calcNum"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static int CallCalcNumDirect(CalcNum calcNum, int a, int b)
        {
            if (calcNum == null)
            {
                throw new ArgumentNullException();
            }
            //写法一
            var result = calcNum(a, b);
            return result;
        }

        /// <summary>
        /// Invoke 方式调用
        /// </summary>
        /// <param name="calcNum"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static int CallCalcNumInvoke(CalcNum calcNum, int a, int b)
        {
            if (calcNum == null)
            {
                throw new ArgumentNullException();
            }
            //写法二
            var result = calcNum.Invoke(a, b);
            return result;
        }

        /// <summary>
        /// DynamicInvoke 方式调用
        /// </summary>
        /// <param name="calcNum"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public static object CallCalcNumDynamicInvoke(CalcNum calcNum,params object[] args)
        {
            if (calcNum == null)
            {
                throw new ArgumentNullException();
            }
            //写法三
            var result = calcNum.DynamicInvoke(args);
            return result;
        }

        /// <summary>
        /// 通过回调函数取值
        /// </summary>
        /// <param name="calcNum"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="action"></param>
        public static void CallCalcNumAsyncCallback(CalcNum calcNum, int a, int b, Action<int> action)
        {
            if (calcNum == null)
            {
                throw new ArgumentNullException();
            }
            //写法四
            calcNum.BeginInvoke(a, b, (cbResult) =>
            {
                Console.WriteLine("CallCalcNumAsyncCallback - 函数执行完成");
                var result = calcNum.EndInvoke(cbResult);
                action(result);
            }, null);

        }

        /// <summary>
        /// 通过循环等待执行
        /// </summary>
        /// <param name="calcNum"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="action"></param>
        public static void CallCalcNumAsyncWhileLoop(CalcNum calcNum, int a, int b, Action<int> action)
        {
            if (calcNum == null)
            {
                throw new ArgumentNullException();
            }
            //写法五
            var cbResult = calcNum.BeginInvoke(a, b, null, null);
            while (!cbResult.IsCompleted)
            {
                Console.WriteLine("请稍后...");
                Task.Delay(1000).Wait();
            }
            Console.WriteLine("CallCalcNumAsyncWhileLoop - 函数执行完成");
            var result = calcNum.EndInvoke(cbResult);
            action(result);
        }
    }
}
